package com.smdp.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.utils.StringUtils;
import com.smdp.utils.AliyunConstants;
import com.smdp.service.AliyunSendSmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.smdp.utils.RedisConstants.LOGIN_CODE_TTL;

/**
 * 阿里云短信服务实现类。
 * 包含发送验证码（包括登录和修改密码）、发送文字短信（提醒用户秒杀开始）。
 *
 * @author 蔡方珩
 */
@Service
@Slf4j
public class AliyunSendSmsServiceImpl implements AliyunSendSmsService {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    /**
     * 发送短信给用户
     * @param phone        接收短信的手机号
     * @param templateCode 短信模板CODE
     * @param codeMap      验证码map 集合
     * @return 发送成功：true / 失败：false
     */
    @Override
    public Boolean sendMessage(String phone, String templateCode, Map<String, Object> codeMap) {

        /*
         * 连接阿里云：
         *
         * 三个参数：
         * regionId 不要动，默认使用官方的
         * accessKeyId 自己的用户accessKeyId
         * accessSecret 自己的用户accessSecret
         */
        DefaultProfile profile = DefaultProfile.getProfile(
                "cn-hangzhou", AliyunConstants.ALIYUN_OPEN_APP_ID, AliyunConstants.ALIYUN_OPEN_APP_SECRET);
        IAcsClient client = new DefaultAcsClient(profile);

        // 构建请求：
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");

        // 自定义参数：
        request.putQueryParameter("PhoneNumbers", phone);// 手机号
        request.putQueryParameter("SignName", "水木点评");// 短信签名
        request.putQueryParameter("TemplateCode", templateCode);// 短信模版CODE

        // 构建短信验证码
        request.putQueryParameter("TemplateParam", JSONObject.toJSONString(codeMap));

        try {
            CommonResponse response = client.getCommonResponse(request);
            log.trace(response.getData());
            return response.getHttpResponse().isSuccess();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 发送验证码给用户
     * @param phone 用户电话号码
     * @return 发送成功/失败信息
     */
    @Override
    public String sendCodeToUser(String phone, String redisPrefix) {
        // 根据手机号从redis中拿验证码
        String code = stringRedisTemplate.opsForValue().get(redisPrefix + phone);
        if (!StringUtils.isEmpty(code)) {
            return phone + " : " + code + "已经存在，还没有过期！";
        }
        // 如果redis中根据手机号拿不到验证码，则生成6位随机验证码
        code = RandomUtil.randomNumbers(6);
        // 验证码存入codeMap，调用aliyunSendSmsService发送短信
        Map<String, Object> codeMap = new HashMap<>();
        codeMap.put("code", code);
        Boolean isSuccess = sendMessage(phone, AliyunConstants.ALIYUN_OPEN_TEMPLATE_CODE, codeMap);
        if (isSuccess) {
            // 如果发送成功，则将生成的6位随机验证码存入redis缓存,2分钟后过期
            stringRedisTemplate.opsForValue().set(redisPrefix + phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);
            return phone + " ： " + code + "发送成功！";
        } else {
            return phone + " ： " + code + "发送失败！";
        }
    }

    /**
     * 发送文字短信给用户
     * @param phone 用户电话号码
     * @return 发送成功/失败信息
     */
    @Override
    public String sendMsgToUser(String phone, String message) {
        // 消息存入codeMap，调用aliyunSendSmsService发送短信
        Map<String, Object> codeMap = new HashMap<>();
        codeMap.put("code", message);
        // 调用aliyunSendSmsService发送短信
        Boolean isSuccess = sendMessage(phone, AliyunConstants.ALIYUN_OPEN_TEMPLATE_MSG, codeMap);
        if (isSuccess) {
            return phone + " ： " + message + "发送成功！";
        } else {
            return phone + " ： " + message + "发送失败！";
        }
    }
}
